Imports System.Security.Principal
Imports System.Threading

Imports Phoenix.DataAccess

Namespace Security

#Region " SecurityRole "
    Public Enum SecurityRole
        Administrator = 2
        Manager = 1
        [Operator] = 0
    End Enum
#End Region

#Region " PhoenixPrincipal "
    Public Class PhoenixPrincipal : Implements IPrincipal, IIdentity

        Public Const AdminRole = "Admin"
        Public Const ManagerRole = "Mananger"
        Public Const OperatorRole = "Operator"

        Private Sub New()

        End Sub

        Public Sub New(ByVal user As DataSetData.Employee)
            Debug.Assert(Not user Is Nothing)
            mUser = user
        End Sub


        Public ReadOnly Property AuthenticationType() As String Implements IIdentity.AuthenticationType
            Get
                Return "Form"
            End Get
        End Property

        Public ReadOnly Property IsAuthenticated() As Boolean Implements IIdentity.IsAuthenticated
            Get
                Return IIf(mUser Is Nothing, False, True)
            End Get
        End Property

        Public ReadOnly Property User() As DataSetData.Employee
            Get
                Return mUser
            End Get
        End Property

        Public ReadOnly Property Name() As String Implements IIdentity.Name
            Get
                Return IIf(mUser Is Nothing, String.Empty, mUser.FullName)
            End Get
        End Property

        Public Overridable ReadOnly Property Identity() As IIdentity Implements IPrincipal.Identity
            Get
                Return Me
            End Get
        End Property

        Public Overridable Function IsInRole(ByVal role As String) As Boolean Implements IPrincipal.IsInRole
            If User Is Nothing Then Return False

            If (role = AdminRole) AndAlso (User.SecurityLevel >= SecurityRole.Administrator) Then Return True
            If (role = ManagerRole) AndAlso (User.SecurityLevel >= SecurityRole.Manager) Then Return True
            If (role = OperatorRole) AndAlso (User.SecurityLevel >= SecurityRole.[Operator]) Then Return True

            Return False
        End Function

        Public Shared ReadOnly Property Empty() As PhoenixPrincipal
            Get
                If mNullPrincipal Is Nothing Then mNullPrincipal = New PhoenixPrincipal
                Return mNullPrincipal
            End Get
        End Property

        Private Shared mNullPrincipal As PhoenixPrincipal
        Private mUser As DataSetData.Employee
    End Class

#End Region

    Module SecurityHelper
        Public Function CurrentUser() As DataSetData.Employee
            Return CType(Thread.CurrentPrincipal, PhoenixPrincipal).User
        End Function

        Public Sub AuthorizateUser(ByVal user As DataSetData.Employee)
            Thread.CurrentPrincipal = New PhoenixPrincipal(user)
        End Sub

        Public Sub ResetUser()
            Thread.CurrentPrincipal = PhoenixPrincipal.Empty
        End Sub

        Public Function IsAdministrator() As Boolean
            Return Thread.CurrentPrincipal.IsInRole(PhoenixPrincipal.AdminRole)
        End Function

        Public Function IsOperator() As Boolean
            Return Thread.CurrentPrincipal.IsInRole(PhoenixPrincipal.OperatorRole)
        End Function

        Public Function IsManager() As Boolean
            Return Thread.CurrentPrincipal.IsInRole(PhoenixPrincipal.ManagerRole)
        End Function

        Public Function CanDeleteEmployee() As Boolean
            Return IsAdministrator()
        End Function

        Public Function CanEditEmployee() As Boolean
            Return IsManager()
        End Function

        Public Function CanCreateEmployee() As Boolean
            Return IsManager()
        End Function

        Public Function CanDeleteClient() As Boolean
            Return IsAdministrator()
        End Function

        Public Function CanCreateProduct() As Boolean
            Return IsManager()
        End Function

        Public Function CanDeleteProduct() As Boolean
            Return IsAdministrator()
        End Function

        Public Function CanCreateService() As Boolean
            Return IsManager()
        End Function

        Public Function CanDeleteService() As Boolean
            Return IsAdministrator()
        End Function

        Public Function UserSecurityRole() As SecurityRole
            Debug.Assert(TypeOf Thread.CurrentPrincipal Is PhoenixPrincipal, "Unexpected security principal")
            Dim user As DataSetData.Employee = CType(Thread.CurrentPrincipal, PhoenixPrincipal).User
            Debug.Assert(Not user Is Nothing, "Unexpected operation for the current security principal")
            Return user.SecurityLevel
        End Function

        Function GetSecurityRoleTitle(ByVal level As Integer) As String
            Select Case level
                Case 0
                    Return Res.RoleTitleUser
                Case 1
                    Return Res.RoleTitleManager
                Case 2
                    Return Res.RoleTitleAdministrator
                Case 3
                    Return Res.RoleTitleUnknown
            End Select

        End Function
    End Module

End Namespace
